package composantes;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Vector;

public class Partie {
	private String 				_nom;
	private int					_nbJoueur;
	private int 				_nbEnergie,
								_nbClic,
								_score[];
	private Dimension			_dimGrille;
	
	private PlaqueCellulaire	_grille;
	private TransfertEnergie 	_transfert;
	
	private int 				_tour;
	
	public Partie(){
		_transfert = new TransfertEnergie();
	}
	
	private void init(int nbJoueur, Dimension dim){
		_tour = 0;
		_nbJoueur = nbJoueur;
		
		_dimGrille = dim;
		_grille = new PlaqueCellulaire(_dimGrille.width, _dimGrille.height);
		_score = new int[nbJoueur];
		for(int i=0;i<nbJoueur;i++)
			_score[i] = 0;
	}
	
	public void initialiserPartie(String nom, int nbJoueur, int nbEnergie, Dimension dimGrille){
		_nom = nom;
		_nbEnergie = nbEnergie;
		init(nbJoueur, dimGrille);
		placerJoueurs();
		_nbClic = 0;
	}
	
	private void placerEnergie(Cellule c, int type){
		try {
			c.setEtat(c.getEtat() + 1);
			c.setType(type);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	/**
	 * Place toutes les énergies d'un seul joueur
	 * @param x Position de départ en X
	 * @param y Position de départ en Y
	 * @throws Exception Si la cellule envoyée en paramètre n'existe pas
	 */
	private int placerJoueur(int nbEnergie, Cellule depart, int type) throws Exception{
		
		if(depart == null)
			throw new Exception("Exception de cellule null");
		
		if(nbEnergie == 0)
			return 0;
		
		Vector<Cellule> v;
		
		while(depart.getEtat() < 2){
			placerEnergie(depart, type);
			nbEnergie--;
			if(nbEnergie == 0)
				return 0;
		}
		
		v = (Vector<Cellule>)_grille.voisins(depart);
		if(v.size() == 0)
			throw new Exception("Exception aucun voisins");
		
		for(Cellule c: v){
			nbEnergie = placerJoueur(nbEnergie, c, type);
		}
		
		return 0;
	}
	
	private Cellule getCoin(int coin){
		switch(coin){
		case 0:		return (Cellule)_grille.getElement(0, 0);
		case 1:		return (Cellule)_grille.getElement(0, _grille.getLargeur()-1);
		case 2:		return (Cellule)_grille.getElement(_grille.getHauteur()-1, 0);
		case 3:		return (Cellule)_grille.getElement(_grille.getHauteur()-1, _grille.getLargeur()-1);
		default: 	return null;
		}
	}
	
	public int get_nbJoueur() {
		return _nbJoueur;
	}

	public int[] get_score() {
		return _score;
	}

	private void placerJoueurs(){
		try{
			for(int i = 0; i < _nbJoueur; i++){
				Integer nbEnergie = _nbEnergie;
				placerJoueur(_nbEnergie, getCoin(i), i);
			}
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
	
	public PlaqueCellulaire getPlaqueCellulaire(){
		return _grille;
	}
	
	public int getTour(){
		return _tour;
	}
	
	public void prochainTour(){
		if(_tour == _nbJoueur-1)
			_tour = 0;
		else
			_tour++;
	}
	
	public void updateScore(ArrayList<Integer> a){
		for(Integer i: a)
			_score[i]++;
	}
	
	public boolean transfertPossible(){
		return _transfert.possible();
	}
	
	public void transferer() throws Exception{
		if(transfertPossible()){
			if(!_transfert.amis())
				_score[_transfert.getSrc().getType()] += 3;
			
			_transfert.transferer();
			
			_grille.vieillir();
			updateScore(_grille.verifier());
		}
		else
			throw new Exception("Exception de transfert impossible");
		
		prochainTour();
	}
	
	public boolean disponible(int x, int y){
		int type = ((Cellule)_grille.getElement(x, y)).getType();
		if(type != _tour && ((Cellule)_grille.getElement(x,y)).getEtat() != 0 && _nbClic == 0)
			return false;
		return true;
	}
	
	public boolean clic(int x, int y){
		if(!disponible(x, y)){
			System.out.println("pas tour");
			return false;
		}
		System.out.println("tour");
		
		
		try{
			if(_transfert.getSrc() == null){
				_transfert.ajouterSrc((Cellule)_grille.getElement(x, y));
				_nbClic++;
			}
			else if(_transfert.getDst() == null)
				if(_transfert.getSrc().estVoisin((Cellule)_grille.getElement(x, y))){
					_transfert.ajouterDst((Cellule)_grille.getElement(x, y));
					_nbClic = 0;
				}
				else{
					_transfert.clear();
					_nbClic = 0;
					throw new Exception("Exception de cellule non voisines");
				}
			else{
				_transfert.clear();
				_transfert.ajouterSrc((Cellule)_grille.getElement(x, y));
			}
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
		
		return true;

	}
	
	public boolean partieTerminee(){
		return _grille.gagnant() != -1;
	}
	
	public int getGagnant(){
		return _grille.gagnant();
	}
	
	public int atteintScore(){
		for(int i=0;i<_nbJoueur;i++){
			if(_score[i] >= 3){
				return _tour;
			}
		}
		
		return -1;
	}
	
}
